from random import *
import numpy as np
from Board import Board
import pyopencl as cl

class BoardOpenCL(Board):
  def __init__(self, nrows, ncols, ctx, queue, mf):
    self.ctx_ = ctx
    self.mf_ = mf
    self.queue = queue
    Board.__init__(self,nrows,ncols)
    self.state_ = np.array( [  0 for j in range(ncols) for i in range(nrows) ])
    self.new_state_ = np.array( self.state_ )

    self.prg = cl.Program(ctx,
      """

      __kernel void kstep(const int nrows, const int ncols, __global bool *state, __global bool *new_state)
      {
    int gti = get_global_id(0);
    int ti = get_local_id(0);
    int n = get_global_size(0);
    int nt  = get_local_size(0); 
    int nb = n/nt;
        for(int jb = 1; jb < nb-1; jb++){
          for(int j = 1; j < nt-1; j++){
                //int n = state[jb*nt-1 + ti-1] + state[jb*nt-1 + ti] + state[jb*nt-1 + ti+1] + state[jb*nt + ti-1] + state[jb*nt + ti+1] + state[jb*nt+1 + ti-1] + state[jb*nt+1 + ti] + state[jb*nt+1 + ti+1];
                int n = state[(jb-1)*nt + ti-1] + state[(jb-1)*nt + ti] + state[(jb-1)*nt + ti+1] + state[jb*nt + ti-1] + state[jb*nt + ti+1] + state[(jb+1)*nt + ti-1] + state[(jb+1)*nt + ti] + state[(jb+1)*nt + ti+1];
                if( n < 2 )
                    new_state[jb*nt + ti] = 0;
                else if( n == 3)
                    new_state[jb*nt + ti] = 1;
                else if( n > 3)
                    new_state[jb*nt + ti] = 0;
                else
                new_state[jb*nt + ti] = state[jb*nt + ti];
      }
    }
      }
      """).build(cache_dir="./kernels")
    
  def _get_state(self,i,j):
    print i, j
    return self.state_[i*self.nrows + j]

  def _set_state(self,i,j, x):
    print i, j, x
    self.state_[i*self.nrows + j] = x

  def step(self):
    pass
    self.state_buffer_ = cl.Buffer(self.ctx_, self.mf_.READ_ONLY | self.mf_.COPY_HOST_PTR, hostbuf=self.state_)
    self.new_state_buffer_ = cl.Buffer(self.ctx_, self.mf_.WRITE_ONLY, self.new_state_.nbytes)
    print "before_step"
    #self.prg.kstep(self.queue, self.state_.shape, None,np.int64(self.nrows), np.int64(self.ncols), self.state_buffer_, self.new_state_buffer_)
    print "after_step"
    print self.state_[0:100]
    #cl.enqueue_copy(self.queue, self.new_state_, self.new_state_buffer_).wait()
    #self.state_ = np.array( self.new_state_ )
    print "after_copy"
    print self.new_state_[0:100]
